<?php

namespace app\api\middleware;

use app\common\repositories\users\UsersRepository;
use support\Container;
use Webman\MiddlewareInterface;
use Webman\Http\Request;
use Webman\Http\Response;
use support\Db;
use support\Log;

use function DI\string;
use function PHPSTORM_META\type;

class CryptMiddleware implements MiddlewareInterface
{
    public $app_key = '';
    public function process(Request $request, callable $next): Response
    {
        // 进入系统前解密
        $app_key = $request->appkey ?? '';
        $this->app_key = $app_key;
        $xapptool_debug = get_xapptool_debug();
        if(!$xapptool_debug){
            $this->decryptPost($request);
            $this->decryptGet($request);
        }

        // 加密响应数据
        $response = $next($request);
        if(!$xapptool_debug){
            $this->encryptResponse($response);
        }
        return $response;
        
    }

    public function encryptResponse($response){
        $res = $response->rawBody();
        if(!empty($res) && is_string($res)) {
            $res = json_decode($res,true);
        }
        if(!empty($res)){
            $res = $this->encryptObjectValues($res);
            $res = json_encode($res,JSON_UNESCAPED_LINE_TERMINATORS | JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            $response->withBody($res);
        }
    }
    public function decryptPost($request){
        $posts = $request->post();
        $posts = $this->decryptObjectValues($posts);
        $request->setPost($posts);
    }

    public function decryptGet($request){
        $gets = $request->get();
        $gets = $this->decryptObjectValues($gets);
        $request->setGet($gets);
    }

    function customEncrypt($input) {
        $input = (string)$input;
        $result = '';
        $salt =  $this->app_key;
        if(empty($input)) return $result;
        for ($i = 0; $i < strlen($input); $i++) {
            // 获取输入字符的 ASCII 码
            $charCode = ord($input[$i]); 
            // 使用异或操作添加盐值的影响
            $charCode = $charCode ^ ord($salt[$i % strlen($salt)]); 
            $result.= chr($charCode);
        }
        return $result;
    }
    
    function customDecrypt($encryptedInput) {
        $result = '';
        $salt =  $this->app_key;
        if(empty($encryptedInput)) return $result;
        for ($i = 0; $i < strlen($encryptedInput); $i++) {
            // 获取加密字符的 ASCII 码
            $charCode = ord($encryptedInput[$i]); 
            // 使用异或操作解密，利用异或的特性：a ^ b ^ b = a
            $charCode = $charCode ^ ord($salt[$i % strlen($salt)]); 
            $result.= chr($charCode);
        }
        return $result;
    }
    function encryptObjectValues($object) {
        $encryptedObj = [];
        if(empty($object)) return $encryptedObj;
        foreach ($object as $key => $value) {
            $encryptKey = $this->customDecrypt($key);
            if(is_array($value)){
                $encryptedObj[$encryptKey] = $this->encryptObjectValues($value);
            }else{
                $encryptedObj[$encryptKey] = $this->customEncrypt($value);
            }
        }
        return $encryptedObj;
    }
    function decryptObjectValues($object) {
        $decryptedObj = [];
        if(empty($object)) return $decryptedObj;
        foreach ($object as $key => $value) {
            $decryptKey = $this->customDecrypt($key);
            if(is_array($value)){
                $decryptedObj[$decryptKey] = $this->decryptObjectValues($value);
            }else{
                $decryptedObj[$decryptKey] = $this->customDecrypt($value);
            }
        }
        return $decryptedObj;
    }
}
